thumbnail
키퍼 홈페이지 리뉴얼 14 - 분산 추적 모니터링 시스템 signoz
keeper_homepage
2023.10.30.

분산 추적 모니터링 시스템으로서 signoz를 한 번 상세하게 알아보겠습니다.

이전 포스팅에서 signoz에 대해 간단하게 알아봤는데요, 이번 포스팅에선 분산 추적 모니터링이라는 키워드에 초점을 맞춰서 signoz를 알아보겠습니다.

앱 여러개 띄워보기

이전 포스팅의 코드에서 간단하게 다른 포트의 앱에게 HTTP 요청을 보낼 수 있는 API를 하나만 더 추가해 보겠습니다.

private final RestTemplate restTemplate;

@GetMapping("/call")
public String call(
        @RequestParam int port,
        @RequestParam(defaultValue = "test") String username) {
    log.info("call localhost:{}...", port);
    String url = "http://localhost:" + port + "/test?username=" + username;
    return restTemplate.getForEntity(url, String.class)
            .getBody();
}

위와 같은 API를 추가한 앱을 여러개 띄워 보겠습니다. (각각 8081~8084 포트를 가집니다.)

스크린샷 2023-10-30 22 42 34

그럼 아래와 같이 service에 앱들이 열린 것을 확인할 수 있습니다.

스크린샷 2023-11-01 13 57 02

앱 끼리 통신해보기

위에서 만들었던 call API를 통해 앱끼리 통신을 해보겠습니다.

  • 8081 -> 8082
  • 8082 -> 8083
  • 8082 -> 8084
  • 8083 -> 8084
image

위와 같이 통신을 하고 나면 Service Map 메뉴를 통해 각 앱이 어디로 트래픽을 보내고 있는지 알 수 있습니다.

스크린샷 2023-11-01 15 04 59

한 번 8082 -> 8083 API 통신에서 Error를 일으켜 보겠습니다.

image

Error를 발생시키고 나면 8083 앱에 문제가 생긴것으로 인식하고 이렇게 앱이 빨간색으로 바뀌게 됩니다.

추가로 8082 - 8083 사이의 선에 마우스를 올려보면 Error Rate가 50% 인 것을 확인할 수 있습니다.

image

여러 앱 사이의 exception 추적

지금처럼 8082 - 8083 사이의 통신에서 exception이 발생했을 때 보통은 양쪽 애플리케이션 로그를 모두 확인해야 합니다.

하지만 signoz는 분산 추적 모니터링을 지원하기 때문에 traceId를 이용해 여러 앱 사이의 추적 로그를 확인할 수 있습니다.

스크린샷 2023-11-01 15 23 13

위와 같이 excepton이 뜨면, 둘 중 하나를 눌러 see the error in trace graph를 눌러봅니다.

스크린샷 2023-11-01 15 28 03

그럼 아래에서 보듯이 8082 - 8083 사이의 모든 stack trace를 보여줍니다. 물론 양쪽 애플리케이션의 로그도 모두 함께 볼 수 있구요.

이런 signoz의 모니터링 능력은 MSA를 사용하거나 해서 애플리케이션간 연결 depth가 깊어지면 깊어질수록 진가를 발휘합니다.

어떻게 여러 앱들 사이에서 종합적인 모니터링이 가능할까?

trace와 span

image

분산 추적에서 추적에 해당하는 trace는 사용자 요청의 시작과 끝을 의미합니다. 그리고 여러개의 span으로 구성되는데, span은 사용자 요청에서 작업을 완료하는 논리적 단위입니다.

span에 대해서 알아야 할 몇 가지만 적어보자면,

  • Root Span: trace의 첫 번째 span을 나타내는 상위 스팬입니다.

  • Child Span: Child Span(자식 스팬)은 부모 스팬에 의해 트리거되며 함수 호출, DB 호출, 다른 서비스에 대한 호출 등이 될 수 있습니다.

  • Duration or Latency: 각 스팬이 프로세스를 완료하는 데 걸리는 시간입니다. 애플리케이션 성능을 분석하는 데 사용되는 주요 데이터 포인트입니다.

  • Causal relationship(인과 관계): 추적은 요청에 관련된 모든 스팬을 순차적 관계로 연관시킵니다.

우리가 Traces 섹션에서 봤던 각각의 bar가 하나의 span이고, 이를 통해 어디서 시간이 오래 걸렸는지 확인할 수 있습니다.

그럼 traceId는 어디서 만들어질까?

그럼 모든 애플리케이션을 지나가는 이 traceId는 어디서 만들어지고, 어떻게 전달될 수 있을까요?

서비스간의 통신에서 상대방이 받은 메시지중에 어떤 메시지가 내가 N번째로 보낸 메시지인지 어떻게 알 수 있을까요?

이는 아주 간단한데, 메시지를 보내는 쪽에서 traceId에 해당하는 태그를 같이 보내주는 것입니다. (이를 위해 javaagent가 필요했습니다.)

TCP나 운영체제의 수준에서 메시지를 추적하려는 시도가 있었지만 프로토콜마다 별도로 구현해야 해 복잡도가 높고 성능이 좋지 않았다. 또한 메시지를 정확하게 추적하기 어려웠다.

출처: 대규모 분산 시스템 추적 플랫폼, Pinpoint

traceId의 특징

수많은 endpoint에서 요청이 들어올 것이고, 마찬가지로 traceId도 무수히 많이 생길 수 밖에 없습니다.

이를 위해 w3c에선 분산 추적 표준을 지정해놨는데요, 그 중 traceId 필드 생성에 대한 고려 사항을 함께 살펴보겠습니다. (이는 권장사항으로 표준은 아닙니다.)

  1. uniqueness
  2. randomness
  3. traceId가 더 짧더라도 호환성을 유지해야함.

중복값이 최대한 적어야하고, 정보 보안을 위해 최대한 랜덤해야 한다고 되어 있습니다.

출처: https://www.w3.org/TR/trace-context/#considerations-for-trace-id-field-generation

마치며

여기까지 signoz에 대해서 알아봤는데요, 마냥 좋기만 할 줄 알았던 signoz에도 큰 단점이 있었습니다.

바로 높은 카디널리티의 식별자에 대한 로그였는데요, 저희 팀은 사용자 문의가 들어오면 특정 요청에 대한 로그를 볼 일이 많은데, 그런 특정 요청에 대해서는 elasticSearch보다 한참 느린 모습을 보여줬습니다.

image

집계 쿼리에 대해선 월등히 빠른 모습을 보여주고 있어서, 팀별로 정말 signoz가 필요한지 다시 한 번 확인하고 사용하는게 좋아보입니다.

Thank You for Visiting My Blog, Have a Good Day 😆
© 2022 정현모, Powered By Gatsby.